package com.example.jni;

import com.example.CaptureProperty;
import com.example.ImageConverter;
import com.example.ImageStitcher;
import com.example.PaneManager;
import com.example.ScrollHandler;
import com.example.ToolbarManager;
import javafx.application.Platform;
import javafx.scene.image.WritableImage;
import org.opencv.core.Mat;

import java.util.List;

/**
 * <p>生成头文件的步骤：</p>
 * <p>1、javac -encoding utf-8 MouseListenerJNI.java</p>
 * <p>2、javah -classpath "D:\idea projects\ScreenShot\src\main\java" -jni com.example.jni.MouseListenerJNI</p>
 * <p>> 注意：生成的头文件于java源文件的全类名强相关，当java源文件的包名变化时，必须重新生成头文件。</p>
 */

public class MouseListenerJNI {
    
    private static class MouseListenerHolder {
        private static final MouseListenerJNI INSTANCE = new MouseListenerJNI();
    }
    
    static {
        // 从java.library.path设置的路径中加载dll，java.library.path在javafx-maven-plugin的options中设置
        System.loadLibrary("libmouse_listener");
    }

    /**
     * 设置监听矩形区域
     * @param left 矩形左边距离屏幕左边的距离
     * @param top 矩形上边距离屏幕上边的距离
     * @param right 矩形右边距离屏幕左边的距离
     * @param bottom 矩形下边距离屏幕上边的距离
     */
    public native void SetListenRect(int left, int top, int right, int bottom);

    /**
     * 获取当前监听矩形区域
     * @param rect [left, top, right, bottom]
     */
    public native void GetListenRect(int[] rect);

    /**
     * 安装鼠标钩子
     * @return 是否安装成功
     */
    public native boolean InstallMouseHook();

    /**
     * 禁用鼠标钩子
     */
    public native void disableMouseHook();

    /**
     * 启用鼠标钩子
     */
    public native void enableMouseHook();

    /**
     * 卸载鼠标钩子
     */
    public native void UninstallMouseHook();

    /**
     * 给dll回调的函数
     */
    private void mouseClickCallBack() {
        System.out.println("callback mouse click");
        PaneManager paneManager = PaneManager.getInstance();
        paneManager.getToolbarManager().autoScrollControl();
    }
    /**
     * dll同步回调完此函数才会触发这一次滚动，这意味着此次截图截的是上一次滚动后的结果
     */
    private void mouseScrollCallBack(int wheelRotation) {
        ToolbarManager toolbarManager = PaneManager.getInstance().getToolbarManager();
        ScrollHandler scrollHandler = ScrollHandler.getScrollHandler();
        System.out.println(wheelRotation > 0 ? "上滚" : "下滚");
        // 转换一下，认为下滚为1，上滚为-1
        wheelRotation = -wheelRotation;
        
        final int finalWheelRotation = wheelRotation;
        
        // 更新步数，这里是dll的单线程同步调用此函数，实际应当不存在并发问题
        synchronized (this) {
            scrollHandler.currentScrollPosition += wheelRotation;
            // 已到过此位置，不必重复截图
            if (scrollHandler.currentScrollPosition < scrollHandler.maxScrollSteps &&
                    scrollHandler.currentScrollPosition > scrollHandler.minScrollSteps) {
                System.out.println("已到过此位置，不必重复截图");
            } else {
                // 没到过此位置，截图并更新最小或最大滚动位置
                Platform.runLater(() -> {
                    // 滚一次截一次图，上滚和下滚图片分别放入两个列表中
                    WritableImage frame = scrollHandler.getFrame();
                    // todo 对比两次截图是否一样
                    Mat frameMat = ImageConverter.writeableImageToMat(frame);
                    Mat lastFrame;
                    if (finalWheelRotation > 0) {
                        List<Mat> downScrollFrameList = scrollHandler.getDownScrollFrameList();
                        System.out.println("downScrollFrameList"+downScrollFrameList.size());
                        lastFrame = downScrollFrameList.get(downScrollFrameList.size() - 1);
                    } else {
                        List<Mat> upScrollFrameList = scrollHandler.getUpScrollFrameList();
                        lastFrame = upScrollFrameList.get(upScrollFrameList.size() - 1);
                    }
                    ImageStitcher.OverlapInfo overlapInfo = ImageStitcher.findOverlapRegion(lastFrame, frameMat);
                    if (overlapInfo.getHeight() > CaptureProperty.SCROLL_FRAME_HEIGHT - 10) {
                        System.out.println("滚到底部了");
                        return;
                    }
                    scrollHandler.saveFrame(frameMat, finalWheelRotation);
                });
                if (scrollHandler.minScrollSteps > scrollHandler.currentScrollPosition) {
                    scrollHandler.minScrollSteps = scrollHandler.currentScrollPosition;
                }
                if (scrollHandler.maxScrollSteps < scrollHandler.currentScrollPosition) {
                    scrollHandler.maxScrollSteps = scrollHandler.currentScrollPosition;
                }
                
            }
        }
        
    }
    
    public static MouseListenerJNI getInstance() {
        return MouseListenerHolder.INSTANCE;
    }
}